Das Thema Programmierfehler unterscheidet Syntax- und logische Fehler. Beide Fehlerarten können zur Entwicklungszeit (at compile time) oder zur Laufzeit (at run time) auftreten. Während praktisch alle Syntaxfehler bereits vom Compiler erkannt werden, liegt es am Entwickler, logische Fehler möglichst früh durch systematisches Testen zu entdecken. Allerdings ist es nicht immer möglich, alle Fehlermöglichkeiten im voraus auszuschalten. Wenn das Laufzeitsystem einen Fehler entdeckt (weil es zum Beispiel eine Datei nicht findet), nennt es den Grund des Fehlers und beendet die Anwendung. Der Entwickler kann mit Fehlerbehandlungscode solche Fehler abfangen und situtations- und benutzeradäquat zu reagieren. Er kann zum Beispiel eine fehlende Ressource substituieren oder den Benutzer auffordern, vor dem nächsten Start den Grund des Fehlers zu bereinigen. Oft hat der Programmierer die Wahl, einen Laufzeitfehler durch Fehlerbehandlungscode abzufangen oder dafür zu sorgen, dass der Benutzer den Fehler gar nicht erst begeht. Wählt er die erste Vorgehensweise, so wird er ...
einen Benutzerfehler provozieren
Formular- oder Berichtsfehler können auftreten, wenn der Fokus auf einem Formular oder Bericht liegt Die Eigenschaftenliste enthält deshalb ein Ereignis Bei Fehler, dessen Ereignisprozedur nach einem Laufzeitfehler ausgeführt wird. Typische Laufzeitfehler in Formularen sind:
Der Benutzer unterlässt die Eingabe in ein Mussfeld
Der Datentyp der Eingabe ist ungültig (zum Beispiel alphabetisch statt nummerisch)
Die Eingabe stammt nicht aus einer vorgegebenen Werteliste
Die Eingabe existiert bereits (doppelt eingegebener Primärschlüssel).
In der Regel ist es nicht möglich, auf alle Fehler spezifisch zu reagieren. Am Ende des Fehlerbehandlungscode steht deshalb eine Catch All-Anweisung, die immer dann eine Systemmeldung anzeigt, wenn der Fehler nicht schon vorher abgefangen worden ist.
Der folgende Fehlerbehandlungscode reagiert im Textfeld TxfZeitbudget des Formulars FrmEssay auf drei Kategorien von Laufzeitfehlern:
auf nichtnummerische Eingaben
auf Eingaben, welche die für TxfZeitbudget definierte Gültigkeitsregel verletzen
auf die übrigen Fehler mit einer Catch All-Anweisung.
Private Sub Form_Error(DataErr As Integer, Response As Integer) If DataErr = cNrDatentypUngültig Then '1 MsgBox "Geben Sie eine Zahl ein.", vbOKOnly+vbExclamation, cHdDatentypUngültig Me.Undo 'fehlerhafte Eingabe löschen Response = acDataErrContinue ElseIf DataErr = cNrGültigkeitsregelVerletzt Then '2 Me.Undo 'fehlerhafte Eingabe löschen 'Formulareigenschaft 'Gültigkeitsmeldung' wird automatisch angezeigt Else '3 MsgBox "'" & DataErr & " " & Error(DataErr) & "' im Formular " & "ESSAYAUFGABE", _ vbOKOnly + vbExclamation, cHdDefault Response = acDataErrContinue End If End Sub
Die Fehlerbehandlungsprozedur Form_Error importiert nach einem Laufzeitfehler den systemdefinierten Fehlercode DataErr und reagiert wie folgt:
cNrDatentypUngültig ist eine benutzerdefinierte benannte Konstante für die systemdefinierte Zahl 2113. Nach dem Auftreten des Fehlers 2113 macht Me.Undo die letzte Eingabe des Formulars rückgängig und fordert den Benutzer auf, eine Zahl statt einer alphabetischen Eingabe einzugeben. cHdDatentypUngültig ist der benutzerdefinierte Standardtitel "Datentyp ungültig" der Meldung. Mit dem systemdefinierten Ausgabeargument acDataErrContinue hält die Fehlerprozedur das Laufzeitsystem von Access an, die Standard-Fehlermeldung zu unterdrücken.
Form_Error zeigt keine Meldung zum Fehler cNrGültigkeitsregelVerletzt. Weil der Rückgabevariablen Response kein Wert zugewiesen wird, benutzt Access die bereits im Eigenschaftenfenster von TxfZeitbudget definierten Gültigkeitseigenschaften: Falls die Gültigkeitsregel >=1 Und <=90 nicht zutrifft, gibt Access die folgende Gültigkeitsmeldung aus: Geben Sie einen Wert zwischen 1 und 90 Minuten ein.
Falls Form_Error auf einen Fehler nicht explizit reagiert, zeigt Access eine Standardfehlermeldung an. Eine Catch All-Anweisung kann diese Meldung in ein benutzerdefiniertes Skelett einbetten. Die oben definierte Catch All-Meldung gibt zum Beispiel in einem Meldungsfenster mit einer OK-Schaltfläche und einem Ausrufezeichen einen Text des folgenden Formats aus:
<Systemdefinierte Fehlernummer> <Systemdefinierter Fehlertext> im Formular ESSAYAUFGABE
DataErr ist der Wert der systemdefinierten Fehlernummer. Der systemdefinierte Fehlertext zu dieser Fehlernummer ist Error(DataErr). cHdDefault ist der benutzerdefinierte Name der Titelkonstante. In TESTS erscheint in der Regel der folgende Text in der Titelleiste der Meldungsbox: "Bitte notieren Sie die Fehlermeldung für Ihren PC-Koordinator".
Eine Fehlerbehandlungsprozedur kann einen Fehler selbst beheben oder ihn durch den Benutzer beheben lassen. Gelingt dies nicht, so wird die Prozedur die Anwendung geordnet verlassen und eine aussagekräftige Fehlermeldung anzeigen. VBA bietet dazu zwei Sprachelemente, die On Error-Anweisung und das Err-Objekt. Wenn die Entwicklerin On Error GoTo <Sprungmarke> zu Beginn einer VBA-Prozedur hinzufügt, dann verzweigt VBA beim Auftreten eines Laufzeitfehlers automatisch zum Fehlerbehandlungscode der Sprungmarke Fehlerbehandlung:. Damit am Ende des Unterprogramms nicht überflüssiger Code (allenfalls mit unerwünschten Nebenwirkungen) ausgeführt wird, muss der Fehlerbehandlungsteil mit Exit Sub bzw. Exit Function übersprungen werden.
Private Sub MCErgebnisskelette_Einfügen(lfTestschlüssel As Long) '-- Vereinbarungen '... On Error GoTo Fehlerbehandlung '-- Code, der Skelette für Mehrfachwahlantworten einfügt '... Exit Sub 'Fehlerbehandlung überspringen Fehlerbehandlung: If Err.Number = cPrimärschlüsselDoppelt Then MsgBox "Skelett bereits vorhanden.", vbOKOnly+vbExclamation, cHdPrimärschlüsselDoppelt End If End Sub
Err.Number ist eine Eigenschaft des Fehlerobjekts Err.
Bei einem Fehler füllt das Laufzeitsystem die Eigenschaften des Err-Objekts automatisch mit einem
Code,
der den Fehler identifiziert. Nach einer benutzerdefinierten Fehlermeldung
verlässt der obige Code das Unterprogramm. Resume springt stattdessen zur
Anweisung unmittelbar nach der fehlerhaften Anweisung zurück.